/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.bomt.service.impl;

import com.comac.ins.bomt.common.enums.BizFileTypeEnum;
import com.comac.ins.bomt.domain.DetailStrengthV2Bom;
import com.comac.ins.bomt.domain.FileExtraInfo;
import com.comac.ins.bomt.domain.vo.*;
import com.comac.ins.bomt.event.InitUploadV2Event;
import com.comac.ins.bomt.event.OriginalBomUploadV2Event;
import com.comac.ins.bomt.repository.BomRepositoryV2;
import com.comac.ins.bomt.service.*;
import com.comac.ins.common.biz.annotations.BizEventListener;
import com.comac.ins.common.biz.domain.model.BizEvent;
import com.comac.ins.common.biz.domain.vo.BizEventInfoVo;
import com.comac.ins.common.biz.enums.BizEventStatusEnum;
import com.comac.ins.common.biz.event.BizEventService;
import com.comac.ins.common.biz.exception.BizException;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.biz.utils.BizAssertUtil;
import com.comac.ins.system.service.ISysConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Bom管理服务实现
 *
 * @author zhanghongyi
 * @date 2024 /8/6 16:30
 * @description BomManageServiceImpl
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class BomManageServiceV2Impl implements BomManageServiceV2 {

    private static final SpelExpressionParser PARSER = new SpelExpressionParser();

    private final BomRepositoryV2 bomRepositoryV2;

    private final BizFileService fileService;

    private final BomFileParseServiceV2 bomFileParseServiceV2;

    private final ISysConfigService configService;

    private final SectionService sectionService;
    @Override
    public Long beginUploadOriginalBom(LoginUser loginUser, MultipartFile file, String aircraftModel, String desc, String track, String groupType) {
        String subTrack = MessageFormat.format("{0}_{1}", aircraftModel, DateFormatUtils.format(new Date(), "yyyy_MM_dd_HHmmssSSSSSS"));
        File fileLocal;
        try {
            fileLocal = File.createTempFile(file.getOriginalFilename() != null? file.getOriginalFilename():"原始装机清单", ".xlsx");
            file.transferTo(fileLocal);
        } catch (IOException e) {
            throw new BizException("transfer exception",e);
        }
        //进行上传入库
        Long eventInfoId = BizEventService.publishEvent(OriginalBomUploadV2Event.builder()
            .loginUser(loginUser)
            .aircraftModel(aircraftModel)
            .track(track)
            .subTrack(subTrack)
            .desc(desc)
            .groupType(groupType)
            .file(fileLocal)
            .fileName(file.getOriginalFilename())
            .build());
        log.info("uploadOriginV2:track:{},subTrack:{},eventId:{}", track,subTrack,eventInfoId);
        BizEventInfoVo eventInfo = BizEventService.queryEventInfoById(eventInfoId);
        BizAssertUtil.isTrue(!StringUtils.equals(BizEventStatusEnum.FAIL.getCode(),eventInfo.getStatus()), eventInfo.getCurrentInfo());
        return  eventInfoId;
    }
    @BizEventListener
    public void doUploadOriginalBom(BizEvent<OriginalBomUploadV2Event> event) {
        OriginalBomUploadV2Event payload = event.getEventPayload();
        //解析
        BizEventService.updateCurrentMsg("解析文件...{}", payload.getFileName());
        List<DetailOriginalV2BomVo> originalBomVos = bomFileParseServiceV2.parseOrigin(payload.getFile());
        List<DetailOriginalV2BomVo> filterOriginalBomDetails = filterOriginalBomDetails(originalBomVos);
        //上传文件
        BizEventService.updateCurrentMsg("文件记录数:{},过滤后记录数:{}",originalBomVos.size(),filterOriginalBomDetails.size(), payload.getFileName());
        FileExtraInfo extra = new FileExtraInfo();
        extra.setBatchDesc(payload.getDesc());
        extra.setBatchNo(payload.getSubTrack());
        BizFileVo fileVo =  fileService.upload(payload.getLoginUser(), BizFileTypeEnum.OBOM, payload.getFile(),payload.getFileName(), payload.getTrack(),payload.getSubTrack(), payload.getAircraftModel(), payload.getGroupType(), extra);
        BizEventService.updateCurrentMsg("保存文件...文件Id:{}", fileVo.getFileId());
        //入库
        OriginalBomV2InfoVo originalBomV2InfoVo = new OriginalBomV2InfoVo();
        originalBomV2InfoVo.setAircraftModel(payload.getAircraftModel());
        originalBomV2InfoVo.setTrack(payload.getTrack());
        originalBomV2InfoVo.setSubTrack(payload.getSubTrack());
        originalBomV2InfoVo.setGroupType(payload.getGroupType());
        originalBomV2InfoVo.setDetails(filterOriginalBomDetails);
        originalBomV2InfoVo.setTrackDesc(payload.getDesc());
        originalBomV2InfoVo.setFileId(fileVo.getFileId());
        originalBomV2InfoVo.setOriginalName(fileVo.getOriginalName());
        bomRepositoryV2.initOriginalBom(payload.getLoginUser(), originalBomV2InfoVo);
    }
    public Long beginUploadInit(LoginUser loginUser, MultipartFile file, String aircraftModel, String desc, String track){
        String subTrack = MessageFormat.format("{0}_{1}", aircraftModel, DateFormatUtils.format(new Date(), "yyyy_MM_dd_HHmmssSSSSSS"));
        Map<String, List<String>> sectionGroupConfig = sectionService.getSectionGroupConfig( aircraftModel, track);
        Map<String, String> reverseSectionGroupConfig = sectionService.getReverseSectionGroupConfig(aircraftModel, track);
        File fileLocal;
        try {
            fileLocal = File.createTempFile(file.getOriginalFilename() != null? file.getOriginalFilename():"原始装机清单", ".xlsx");
            file.transferTo(fileLocal);
        } catch (IOException e) {
            throw new BizException("transfer exception",e);
        }
        //进行上传入库
        Long eventInfoId = BizEventService.publishEvent(InitUploadV2Event.builder()
            .loginUser(loginUser)
            .aircraftModel(aircraftModel)
            .track(track)
            .subTrack(subTrack)
            .desc(desc)
            .file(fileLocal)
            .fileName(file.getOriginalFilename())
            .sectionGroupConfig(sectionGroupConfig)
            .reverseSectionGroupConfig(reverseSectionGroupConfig)
            .build());
        log.info("uploadInitV2:track:{},subTrack:{},eventId:{}", track,subTrack,eventInfoId);
        BizEventInfoVo eventInfo = BizEventService.queryEventInfoById(eventInfoId);
        BizAssertUtil.isTrue(!StringUtils.equals(BizEventStatusEnum.FAIL.getCode(),eventInfo.getStatus()), eventInfo.getCurrentInfo());
        return eventInfoId;
    }
    @BizEventListener
    public void doUploadInit(BizEvent<InitUploadV2Event> evt){
        InitUploadV2Event event = evt.getEventPayload();
        LoginUser loginUser = event.getLoginUser();
        Map<String, String> reverseSectionGroupConfig = event.getReverseSectionGroupConfig();
        Map<String, List<String>> sectionGroupConfig = event.getSectionGroupConfig();
        File file = event.getFile();
        String aircraftModel = event.getAircraftModel();
        String track = event.getTrack();
        String subTrack = event.getSubTrack();
        BizEventService.updateCurrentMsg("解析标准装机清单...{}", event.getFileName());
        Map<String, List<DetailStandardV2BomVo>> groupedStandard = bomFileParseServiceV2.parseStandard(loginUser, file, aircraftModel, track,subTrack);
        groupedStandard.forEach((key, value) -> {
            BizAssertUtil.isTrue(reverseSectionGroupConfig.containsKey(key), MessageFormat.format("未找到机型:{0},批次号:{1},部段:{2}对应的编码,请前往构型定义添加",aircraftModel,track,key));
        });
        BizEventService.updateCurrentMsg("解析强度数模清单...{}", event.getFileName());
        Map<String, List<DetailStrengthV2Bom>> groupedStrength = bomFileParseServiceV2.parseStrength(loginUser, file, aircraftModel, track,subTrack);
        groupedStrength.forEach((key, value) -> {
            BizAssertUtil.isTrue(sectionGroupConfig.containsKey(key), MessageFormat.format("未找到机型:{0},批次号:{1},编码:{2}对应的部段,请前往构型定义添加",aircraftModel,track,key));
        });
        BizEventService.updateCurrentMsg("保存初始化文件...{}", event.getFileName());
        FileExtraInfo extra = new FileExtraInfo();
        extra.setBatchDesc(event.getDesc());
        extra.setBatchNo(event.getSubTrack());
        fileService.upload(event.getLoginUser(), BizFileTypeEnum.INIT, event.getFile(),event.getFileName(), event.getTrack(), event.getSubTrack(), event.getAircraftModel(), null, extra);
        Map<String,Long> sectionStandardInfoIdMap = bomRepositoryV2.initStandardBom(event.getLoginUser(), null,groupedStandard,event.getDesc());
        for( Map.Entry<String, List<DetailStrengthV2Bom>>entry :groupedStrength.entrySet()){
            bomRepositoryV2.initStrengthBom(event.getLoginUser(), entry.getKey(),event.getSectionGroupConfig().get(entry.getKey()).get(0),null,entry.getValue(),sectionStandardInfoIdMap);
        }
    }

    @Override
    public void deleteOriginalBomDetails(LoginUser loginUser, List<Long> ids) {
        bomRepositoryV2.deleteOriginalBomDetails(loginUser, ids);
    }
    @Override
    public void deleteOriginalBomInfos(LoginUser loginUser, List<Long> ids) {
        bomRepositoryV2.deleteOriginalBomInfos(loginUser, ids);
    }

    @Override
    public void modifyOriginalBom(LoginUser loginUser, DetailOriginalV2BomVo modifyDetail) {
        bomRepositoryV2.modifyOriginalBom(loginUser, modifyDetail);
    }

    @Override
    public void copyStandardBom(LoginUser loginUser, Long srcStandardBomId, List<Long> deleteDetailIds,List<DetailStandardV2BomVo> modifyDetails, String desc) {
        bomRepositoryV2.copyStandardBom(loginUser, srcStandardBomId, deleteDetailIds,modifyDetails, desc);
    }
    @Override
    public void modifyStrengthBom(LoginUser loginUser, Long srcStrengthBomId, List<Long> deleteDetailIds,List<DetailStrengthV2BomVo> modifyDetails, String desc) {
        bomRepositoryV2.modifyStrengthBom(loginUser, srcStrengthBomId, deleteDetailIds,modifyDetails, desc);
    }

    private  List<DetailOriginalV2BomVo> filterOriginalBomDetails(List<DetailOriginalV2BomVo> originalBomDetails){
        String filterConfig = configService.selectConfigByKey("original.filter.express");
        if(StringUtils.isBlank(filterConfig)){
            filterConfig = "T(java.util.Arrays).asList('50','51','53','54','55','56','57').contains((ata?:'null').split('-')[0])";
        }
        Expression expression = PARSER.parseExpression(filterConfig);
        return originalBomDetails.stream().filter(detail -> {
            StandardEvaluationContext context = new StandardEvaluationContext(detail);
            Boolean keep = expression.getValue(context, Boolean.class);
            return !BooleanUtils.isFalse(keep);
        }).collect(Collectors.toList());
    }
}

